﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using xbd.DataConvertLib;
using xbd.s7netplus;
using DataType = xbd.s7netplus.DataType;

namespace lyh.FG2JiaYaZhanDemo
{

    /// <summary>
    /// 通信类
    /// </summary>
    public  class S7NetLib
    {

        private Plc simensPlc;

        /// <summary>
        /// 加锁
        /// </summary>
        private static object objLock = new object();
        public CpuType CpuType { get; set; }
        public string IPAddress { get; set; }
        public short  Rack { get; set; }
        public short  Slot { get; set; }
        
        public S7NetLib(CpuType cpuType, string ipAddress, short  rack, short  slot)
        {
            CpuType = cpuType;
            IPAddress = ipAddress;
            Rack = rack;
            Slot = slot;            
        }
        public S7NetLib()
        { }

        /// <summary>
        /// 建立连接
        /// </summary>
        /// <returns></returns>
        public OperateResult Connect()
        {
            try 
            {
                if (this.simensPlc != null && this.simensPlc.IsConnected)
                {
                    this.simensPlc.Close();
                    this.simensPlc = null;
                }

                
                simensPlc = new Plc(this.CpuType, IPAddress, Rack, Slot);
                simensPlc.Open();
                return OperateResult.CreateSuccessResult();
            }
            catch (Exception ex)
            {
                Debug.WriteLine("连接失败"+ex);
                return OperateResult.CreateFailResult(ex.Message);
            }            
        }


        /// <summary>
        /// 断开连接
        /// </summary>
        public void DisConnect()
        {
            if (this.simensPlc != null && this.simensPlc.IsConnected)
            {
                this.simensPlc.Close();
            }

        }

        /// <summary>
        /// 读取字节数组数据
        /// </summary>
        /// <param name="dataType"></param>
        /// <param name="db"></param>
        /// <param name="start"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public OperateResult<byte[]> ReadByteArray(DataType dataType, int db, int start, int count)
        {
            if (this.simensPlc != null && this.simensPlc.IsConnected)
            {
                try
                {
                    lock (objLock)
                    {
                        return OperateResult.CreateSuccessResult(simensPlc.ReadBytes(dataType, db, start, count));
                    }                    
                }
                catch (Exception ex)
                {
                    return OperateResult.CreateFailResult<byte[]>("读取失败："+ ex.Message);
                }                
            }
            else 
            { 
                return OperateResult.CreateFailResult<byte[]>("请检查PLC链接是否正确");
            }
        }


        /// <summary>
        /// 读取单个变量数据
        /// </summary>
        /// <param name="varAddress"></param>        
        /// <returns></returns>
        public OperateResult<object > ReadVariable(string varAddress)
        {
            if (this.simensPlc != null && this.simensPlc.IsConnected)
            {
                try
                {
                    lock (objLock)
                    {
                        return OperateResult.CreateSuccessResult(simensPlc.Read(varAddress));
                    }
                }
                catch (Exception ex)
                {
                    return OperateResult.CreateFailResult<object >("读取失败：" + ex.Message);
                }
            }
            else
            {
                return OperateResult.CreateFailResult<object >("请检查PLC链接是否正确");
            }
        }


        /// <summary>
        /// 读取类对象数据
        /// </summary>
        /// <param name="db"></param>
        /// <param name="start"></param>
        /// <returns></returns>
        public OperateResult<T> ReadClass<T>(int db ,int start) where T : class
        {
            if (this.simensPlc != null && this.simensPlc.IsConnected)
            {
                try
                {
                    lock (objLock)
                    {
                        return OperateResult.CreateSuccessResult(simensPlc.ReadClass<T>(db, start));
                    }
                }
                catch (Exception ex)
                {
                    return OperateResult.CreateFailResult<T>("读取失败：" + ex.Message);
                }
            }
            else
            {
                return OperateResult.CreateFailResult<T>("请检查PLC链接是否正确");
            }
        }


        /// <summary>
        /// 写入单个变量数据
        /// </summary>
        /// <param name="varAddress"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public OperateResult WriteVariable(string varAddress, object value)
        {
            if (this.simensPlc != null && this.simensPlc.IsConnected)
            {
                try
                {
                    lock (objLock)
                    {
                        simensPlc.Write(varAddress, value);
                        return OperateResult.CreateSuccessResult();
                    }
                }
                catch (Exception ex)
                {
                    return OperateResult.CreateFailResult("写入失败：" + ex.Message);
                }
            }
            else
            {
                return OperateResult.CreateFailResult("请检查PLC链接是否正确");
            }
        }

    }
}
